package com.yanqu.road.server.manager.tomb;


import com.google.protobuf.AbstractMessage;
import com.yanqu.road.entity.activity.ActivityConditionInfo;
import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.ActivityTableExt;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.rank.yrank.UserYRank;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroup;
import com.yanqu.road.logic.activity.tomb.config.TombConfig;
import com.yanqu.road.logic.activity.tomb.config.entity.*;
import com.yanqu.road.logic.bussiness.servercenter.ActivityBussiness;
import com.yanqu.road.logic.cross.CrossActivityRankListModel;
import com.yanqu.road.pb.rank.RankProto;
import com.yanqu.road.pb.tomb.Tomb;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityRankMgr;
import com.yanqu.road.server.manager.config.GoodsMgr;
import com.yanqu.road.server.manager.tomb.astar.Coordinate;
import com.yanqu.road.server.manager.tomb.business.TombCrossBusiness;
import com.yanqu.road.server.manager.tomb.entity.*;
import com.yanqu.road.server.manager.tomb.event.Buff;
import com.yanqu.road.server.manager.union.activitygroup.Cross2UnionActivityGroupMgr;
import com.yanqu.road.server.manager.yrank.CrossYRankCacheMgr;
import com.yanqu.road.server.manager.yrank.CrossYRankMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.sync.message.SyncResponse;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.time.Instant;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

public class TombActivity {
    private static Logger logger = LogManager.getLogger(TombActivity.class.getName());

    private ActivityInfo activityInfo;

    //groupId
    private Map<Integer, Map<Integer, TombMaze>> tombMazeMap = new ConcurrentHashMap<>();


    private Map<String, TombActivityUnion> activityUnionMap = new ConcurrentHashMap<>();


    private TombConfig config;

    private TombHeartbeat heartbeat;

    private TombLog tombLog;

    private TombDbData dbData;

    //groupId
    private Map<Integer, AtomicBoolean> initializedMap = new ConcurrentHashMap<>();


    public TombActivity(ActivityInfo activityInfo) {
        logger.info("正在加载秦始皇陵墓的活动数据，活动ID{}", activityInfo.getActivityId());
        this.activityInfo = activityInfo;
        this.heartbeat = TombHeartbeat.newInstance(this.activityInfo.getActivityId());
        this.dbData = TombDbData.newInstance(this);
        this.tombLog = TombLog.newInstance(this);
        for (int groupId : TombServiceMgr.getGroupListByCrossServerId(activityInfo.getActivityId())) {
            this.initializedMap.put(groupId, new AtomicBoolean(false));
        }
    }

    public void loadConfig() {
        List<Integer> list = new ArrayList<>();
        list.add(this.activityInfo.getActivityId());
        logger.info("正在加载秦始皇陵墓的配置信息");
        Map<Integer, List<ActivityConditionInfo>> activityConditionInfoMap = ActivityBussiness.getOpenCrossRankActivityConditionInfoMap(list);
        Map<Integer, Map<String, ActivityConfig>> activityConfigMap = ActivityBussiness.getActivityConfigMap(list);
        Map<Integer, List<ActivityTableExt>> activityTableExtMap = ActivityBussiness.getActivityTableExtMap(list);
        Map<String, ActivityConfig> configMap = activityConfigMap.get(this.getActivityInfo().getActivityId());
        List<ActivityTableExt> activityTableExts = activityTableExtMap.get(this.getActivityInfo().getActivityId());
        this.config = new TombConfig(configMap, activityTableExts);
        List<ActivityConditionInfo> activityConditionInfos = activityConditionInfoMap.get(this.activityInfo.getActivityId());
        if (activityConditionInfos != null) {
            for (ActivityConditionInfo activityConditionInfo : activityConditionInfos) {
                if (activityConditionInfo.getType() != eGamePlayerEventType.TombUserRank.getValue()) {
                    continue;
                }
                int i = activityConditionInfo.getParamList().get(1).intValue();
                if (this.getConfig().getMaxRank() < i) {
                    this.getConfig().setMaxRank(i);
                }
            }
        }
        logger.info("加载秦始皇陵墓配置完成！");
        this.config.setRepairItemProgress(GoodsMgr.getGoodsInfo(config.getConfig().getTOMB_REPAIR_ITEM_ID()).getParamList().get(0).intValue());  //拿黏土可修复进度
    }

    public void loadData() {
        logger.info("正在加载秦始皇陵墓的地图数据，玩家数据");
        Map<Integer, DbActivityTombInfo> dbActivityTombInfoMap = TombCrossBusiness.getDbActivityTombInfo(this.activityInfo.getActivityId());
        this.dbData.setDbActivityTombInfoMap(dbActivityTombInfoMap);

        int mapNum = 0;
        Map<Integer, Map<Integer, DbTombMaze>> dbTombMazeMap = TombCrossBusiness.getDbTombMaze(this.activityInfo.getActivityId());
        for (Map.Entry<Integer, Map<Integer, DbTombMaze>> mapEntry : dbTombMazeMap.entrySet()) {
            for (DbTombMaze dbTombMaze : mapEntry.getValue().values()) {
                this.dbData.addDbTombMaze(dbTombMaze);
                if(!this.tombMazeMap.containsKey(dbTombMaze.getGroupId())){
                    this.tombMazeMap.put(dbTombMaze.getGroupId(), new ConcurrentHashMap<>());
                }
                if (this.tombMazeMap.get(dbTombMaze.getGroupId()).containsKey(dbTombMaze.getFloor())) {
                    continue;
                }
                logger.info("正在加载秦始皇陵墓的地图数据，地图层数{},{}", dbTombMaze.getGroupId(), dbTombMaze.getFloor());
                TombMaze tombMaze = new TombMaze(dbTombMaze, this);
                this.tombMazeMap.get(dbTombMaze.getGroupId()).put(tombMaze.getFloor(), tombMaze);
                logger.info("加载秦始皇陵墓的地图数据完成！，地图层数{},{}", dbTombMaze.getGroupId(), dbTombMaze.getFloor());
                mapNum++;
            }
        }
        logger.info("加截地图数据完成！数量{}", mapNum);
        for (Map.Entry<Integer, Map<Integer, DbTombMaze>> mapEntry : dbTombMazeMap.entrySet()) {
            if(!initializedMap.containsKey(mapEntry.getKey())){
                initializedMap.put(mapEntry.getKey(), new AtomicBoolean(true));
            }else {
                initializedMap.get(mapEntry.getKey()).set(true);
            }
        }

        Map<Long, DbTombUser> dbTombUserMap = TombCrossBusiness.getDbTombUser(this.activityInfo.getActivityId());
        for (DbTombUser dbTombUser : dbTombUserMap.values()) {
            this.dbData.addDbTombUser(dbTombUser);
        }
        Map<String, DbTombPosition> dbTombPositionMap = TombCrossBusiness.getDbTombPosition(this.activityInfo.getActivityId(), 0);
        for (DbTombPosition dbTombPosition : dbTombPositionMap.values()) {
            this.dbData.addDbTombPosition(dbTombPosition);
            for (Map.Entry<String, DigUserInfo> digUserInfoEntry : dbTombPosition.getDigUnionUserMap().entrySet()) {
                this.getActivityUnion(digUserInfoEntry.getKey()).addDbTombPosition(dbTombPosition);
            }
        }
        logger.info("加截地图对应位置信息完成！");

        Map<Long, DbTombUserPosition> dbTombUserPositionMap = TombCrossBusiness.getDbTombUserPosition(this.activityInfo.getActivityId());
        for (DbTombUserPosition dbTombUserPosition : dbTombUserPositionMap.values()) {
            this.dbData.addDbTombUserPosition(dbTombUserPosition);
        }
        for (int groupId : TombServiceMgr.getGroupListByCrossServerId(activityInfo.getActivityId())) {
            this.dbData.getDbActivityTombInfo(groupId);
        }
        logger.info("加截地图玩家对应位置信息完成！");
        logger.info("正在加载秦始皇陵墓的活动数据 完成！");
    }

    public DbActivityTombInfo getDbActivityTombInfo(int groupId) {
        return this.dbData.getDbActivityTombInfo(groupId);
    }

    public Map<Integer, DbActivityTombInfo> getDbActivityTombInfoMap() {
        return this.dbData.getDbActivityTombInfoMap();
    }

    public void generateMaze(int groupId ) {

        DbActivityTombInfo dbActivityTombInfo = this.getDbActivityTombInfo(groupId);
        if(dbActivityTombInfo == null){
            return;
        }
        int floor = dbActivityTombInfo.getMaxExploreFloor() + 4;
        if (floor > dbActivityTombInfo.getMaxFloor()) {
            dbActivityTombInfo.setMaxFloor(floor);
            dbActivityTombInfo.refreshUpdateTime();
        }
        for (int i = 1; i <= dbActivityTombInfo.getMaxFloor(); i++) {
            DbTombMaze dbTombMaze = this.dbData.getDbTombMaze(groupId, i);
            if (dbTombMaze == null) {
                dbTombMaze = this.initDbTombMaze(groupId, i);
                this.dbData.addDbTombMaze(dbTombMaze);
            }
        }
        Map<Integer, DbTombMaze> dbTombMazeMap = this.dbData.getDbTombMazeMap(groupId);
        for (DbTombMaze dbTombMaze : dbTombMazeMap.values()) {
            if(!tombMazeMap.containsKey(groupId)){
                tombMazeMap.put(groupId, new ConcurrentHashMap<>());
            }
            if (this.tombMazeMap.get(groupId).containsKey(dbTombMaze.getFloor())) {
                continue;
            }
            logger.info("正在加载秦始皇陵墓的地图数据，地图层数{}, 分组{}", dbTombMaze.getFloor(), groupId);
            TombMaze tombMaze = new TombMaze(dbTombMaze, this);
            this.tombMazeMap.get(groupId).put(tombMaze.getFloor(), tombMaze);
            logger.info("加载秦始皇陵墓的地图数据完成！，地图层数{}, 分组{}", dbTombMaze.getFloor(), groupId);

        }

    }


    public void getConfigInfo(Tomb.TombConfigInfoResp.Builder builder) {
        for (ActivityTombEvent configEvent : this.config.getEvents()) {
            Tomb.TombEventConfigTemp.Builder temp = Tomb.TombEventConfigTemp.newBuilder();
            temp.setId(configEvent.getId());
            temp.setEventType(configEvent.getEventType());
            temp.setNpcId(configEvent.getNpcId());
            temp.setNpcBookmark(configEvent.getNpcBookmark());
            temp.addAllScore(configEvent.getScore());
            temp.setReward(PropertyHelper.parsePropertyToString(configEvent.getReward()));
            builder.addEventConfigList(temp);
        }

        for (ActivityTombBookmark bookmark : this.config.getBookmarks()) {
            Tomb.TombBookmarkConfigTemp.Builder temp = Tomb.TombBookmarkConfigTemp.newBuilder();
            temp.setId(bookmark.getId());
            temp.setName(bookmark.getName());
            temp.setEventType(bookmark.getEventType());
            temp.setSubclassName(bookmark.getSubclassName());
            temp.setSubclassDesc(bookmark.getSubclassDesc());
            temp.setIcon(bookmark.getIcon());
            temp.setQuality(bookmark.getQuality());
            builder.addBookmarkConfigList(temp);
        }

        for (ActivityTombFloor floor : this.config.getFloors()) {
            Tomb.TombFloorConfigTemp.Builder temp = Tomb.TombFloorConfigTemp.newBuilder();
            temp.setId(floor.getId());
            temp.addAllFloor(floor.getFloor());
            temp.setEnergy(floor.getEnergy());
            for (List<Integer> integerList : floor.getEventWeight()) {
                Tomb.IntArray.Builder intArray = Tomb.IntArray.newBuilder();
                intArray.addAllIntArray(integerList);
                temp.addEventWeight(intArray);
            }
            builder.addFloorConfigList(temp);
        }

        for (ActivityTombRepair repair : this.config.getRepairs()) {
            Tomb.TombRepairConfigTemp.Builder temp = Tomb.TombRepairConfigTemp.newBuilder();
            temp.setId(repair.getId());
            temp.setDesc(repair.getDesc());
            temp.setMaxSchedule(repair.getSchedule());
            temp.setName(repair.getName());
            builder.addRepairConfigList(temp);
        }

    }

    public synchronized void enterMaze(long userId, long serverId, Tomb.TombEnterMazeReq req, Tomb.TombEnterMazeResp.Builder builder) {
        UserInfo userInfo = UserInfo.newInstance(req.getPlayerBaseData());
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId);
        if (dbTombUser == null) {
            return;
        }
        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        for (Tomb.TombDollInfo tombDollInfo : req.getDollList()) {
            if (!dbTombUser.getDollMap().containsKey(tombDollInfo.getDollId())) {
                dbTombUser.getDollMap().put(tombDollInfo.getDollId(), tombDollInfo.getExpireTime());
                dbTombUser.refreshUpdateTime();
                continue;
            }
            long expireTime = dbTombUser.getDollMap().get(tombDollInfo.getDollId());
            if (tombDollInfo.getExpireTime() > expireTime) {
                dbTombUser.getDollMap().put(tombDollInfo.getDollId(), tombDollInfo.getExpireTime());
                dbTombUser.refreshUpdateTime();
            }
        }

        synchronized (dbTombUser.getPvpUnionChooseMap()) {
            dbTombUser.setUserInfo(userInfo);
            dbTombUser.setAttackAddition(req.getAttackAddition());
            dbTombUser.setHpAddition(req.getHpAddition());
            dbTombUser.addPartnerInfoList(req.getPartnerListList());

            Tomb.CoordinateTemp.Builder coordinateTempBuilder = Tomb.CoordinateTemp.newBuilder();
            coordinateTempBuilder.setRow(dbTombUser.getX());
            coordinateTempBuilder.setColumn(dbTombUser.getY());
            coordinateTempBuilder.setFloor(dbTombUser.getFloor());

            TombMaze tombMaze = this.getTombMaze(groupId, dbTombUser.getFloor());
            if (dbTombUser.getX() == 0 && dbTombUser.getY() == 0) {
                Coordinate birthplace = tombMaze.getBirthplace(dbTombUser);
                dbTombUser.setX(birthplace.getX());
                dbTombUser.setY(birthplace.getY());
            }

            Tomb.AllyInfo.Builder allyInfoBuilder = dbTombUser.toAllyInfoBuilder();
            //通知下一层
            this.moveNotify(tombMaze.getFloor(), coordinateTempBuilder.build(), dbTombUser, null, allyInfoBuilder);
            if (dbTombUser.getGoDownstairs() == 1) {
                dbTombUser.setGoDownstairs(0);
                dbTombUser.setFloor(dbTombUser.getFloor() + 1);
                tombMaze = this.getTombMaze(groupId, dbTombUser.getFloor());
                Coordinate birthplace = tombMaze.getBirthplace(dbTombUser);
                dbTombUser.setX(birthplace.getX());
                dbTombUser.setY(birthplace.getY());
                dbTombUser.refreshUpdateTime();
                DbActivityTombInfo dbActivityTombInfo = this.dbData.getDbActivityTombInfo(groupId);
                if (tombMaze.getFloor() > dbActivityTombInfo.getMaxExploreFloor()) {
                    dbActivityTombInfo.setMaxExploreFloor(tombMaze.getFloor());
                    dbActivityTombInfo.refreshUpdateTime();
                }
                if (dbActivityTombInfo.getIsBossDead() == 0) {
                    if (dbActivityTombInfo.getBossFloor() - this.config.getConfig().getTOMB_BOSS_TRIGGER_RULE() <= tombMaze.getFloor()) {
                        long epochSecond = Instant.now().getEpochSecond();
                        long diff = activityInfo.getEndTime() - epochSecond;
                        diff = diff / 3600;
                        int downFloor = 0;
                        List<List<Integer>> tombBossDropRule = this.config.getConfig().getTOMB_BOSS_DROP_RULE();
                        for (int i = tombBossDropRule.size() - 1; i >= 0; i--) {
                            if (diff > tombBossDropRule.get(i).get(0)) {
                                downFloor = tombBossDropRule.get(i).get(1);
                            }
                        }
                        if (downFloor > 0) {
                            dbActivityTombInfo.setBossFloor(dbActivityTombInfo.getBossFloor() + downFloor);
                            dbActivityTombInfo.refreshUpdateTime();
                            Tomb.TombBossGoDownstairsPush.Builder pushBuilder = Tomb.TombBossGoDownstairsPush.newBuilder();
                            pushBuilder.setEventUserInfo(dbTombUser.toEventUserInfoBuilder());
                            pushBuilder.setAddFloor(downFloor);
                            pushBuilder.setBossFloor(dbActivityTombInfo.getBossFloor());

                            Map<Long, Tomb.TombBossGoDownstairsPushCrossToGameReq.Builder> crossToGameReqMap = new HashMap<>();
                            List<HeartbeatInfo> list = this.heartbeat.getList(groupId);
                            for (HeartbeatInfo heartbeatInfo : list) {
                                if (!crossToGameReqMap.containsKey(heartbeatInfo.getServerId())) {
                                    Tomb.TombBossGoDownstairsPushCrossToGameReq.Builder builder1 = Tomb.TombBossGoDownstairsPushCrossToGameReq.newBuilder();
                                    builder1.setTriggerServerId(dbTombUser.getUserInfo().getServerId());
                                    builder1.setTriggerUserId(dbTombUser.getUserId());
                                    crossToGameReqMap.put(heartbeatInfo.getServerId(), builder1.setResp(pushBuilder));
                                }
                                crossToGameReqMap.get(heartbeatInfo.getServerId()).addUserIdList(heartbeatInfo.getUserId());
                            }
                            crossToGameReqMap.forEach((_serverId, _req) -> {
                                MessageHelper.sendToGameServer(_serverId, GameProtocol.S_TOMB_BOSS_GO_DOWNSTAIRS_PUSH, this.getActivityInfo().getActivityId(), dbTombUser.getUserId(), _req, null);
                            });

                            //日志
                            DbTombLog dbTombLog = DbTombLog.newInstance();
                            dbTombLog.setUid(String.valueOf(this.activityInfo.getActivityId()));
                            dbTombLog.setFloor(tombMaze.getFloor());
                            dbTombLog.setFromUserId(dbTombUser.getUserId());
                            dbTombLog.setLogEnum(Tomb.TombLogEnum.TombLogEnum_Boss_Go_downstairs_VALUE);
                            dbTombLog.setEventId(0);
                            dbTombLog.setValue1(downFloor);
                            dbTombLog.setEnergy(dbTombUser.getEnergy(tombMaze.getConfig().getConfig()));
                            dbTombLog.setDescription("秦始皇下楼");
                            dbTombLog.setGroupId(groupId);
                            tombMaze.getActivity().getTombLog().addDbTombLog(dbTombLog, true);
                        }
                    }
                }

            }
            // 检查玩偶是否过期
            TombServiceMgr.checkDollOverTime(activityInfo.getActivityId(), dbTombUser);
            dbTombUser.refreshUpdateTime();


            if (tombMaze.getDbTombMaze().getFirstIntoUserId() == 0) {
                tombMaze.getDbTombMaze().setFirstIntoUserId(dbTombUser.getUserId());
                tombMaze.getDbTombMaze().refreshUpdateTime();
                DbActivityTombInfo dbActivityTombInfo = this.getDbActivityTombInfo(groupId);
                if (dbActivityTombInfo.getMaxExploreFloor() < tombMaze.getFloor()) {
                    dbActivityTombInfo.setMaxExploreFloor(tombMaze.getFloor());
                    dbActivityTombInfo.refreshUpdateTime();
                }
            }
            Tomb.TombEliteNpcInfoPush.Builder eliteNpcInfo = tombMaze.getEliteNpcInfo(dbTombUser);
            if (eliteNpcInfo != null) {
                builder.setEliteNpcInfoPush(eliteNpcInfo);
            }
            builder.addAllDoorList(tombMaze.getDoorList());

            builder.setRowNum(tombMaze.getDbTombMaze().getMaze().getMaxRow());
            builder.setColumnNum(tombMaze.getDbTombMaze().getMaze().getMaxColumn());
            builder.setFloor(dbTombUser.getFloor());
            builder.addAllList(this.getAlliInfoList(tombMaze.getFloor(), dbTombUser.getUserId(), dbTombUser.getUserInfo().getUnionUid()));
            builder.setAlive(dbTombUser.getStatus() != 2);
            builder.setBossFloor(this.dbData.getDbActivityTombInfo(groupId).getBossFloor());
            int upgradeTimes = this.dbData.getUpgradeTimes(tombMaze.getFloor(), userId);
            builder.setUpgradeTimes(upgradeTimes);


            if (dbTombUser.getStatus() == 2 && dbTombUser.getAttackUserId() > 0) {
                DbTombUser dbTombUser1 = this.dbData.getDbTombUser(dbTombUser.getAttackUserId());
                if (dbTombUser1 != null) {
                    builder.setAttackUser(dbTombUser1.toEventUserInfoBuilder());
                }
            }
            Tomb.TombNpcInfoPush.Builder npcInfo = tombMaze.getNpcInfo();
            builder.addAllNpc(npcInfo.getInfoList());

            Tomb.PositionTemp.Builder p = Tomb.PositionTemp.newBuilder();
            p.setRow(dbTombUser.getX());
            p.setColumn(dbTombUser.getY());

            builder.setMyPosition(p);
            Tomb.UserInfo.Builder userInfoBuilder = dbTombUser.toUserInfoBuilder(this.config.getConfig());

//            List<UserYRank> userYRankList = CrossYRankMgr.getSortUserRankList(this.activityInfo.getActivityId(), groupId, String.valueOf(eGamePlayerEventType.TombUserRank.getValue()));
//            if (userYRankList != null) {
            RankProto.RankListMsg.Builder rankBuilder = CrossYRankCacheMgr.getUserRankList(this.activityInfo.getActivityId(), groupId, String.valueOf(eGamePlayerEventType.TombUserRank.getValue()));
            int myRank = CrossYRankCacheMgr.getUserRank(this.activityInfo.getActivityId(), groupId, String.valueOf(eGamePlayerEventType.TombUserRank.getValue()), rankBuilder, dbTombUser.getUserId());
//                int myRank = CrossYRankMgr.getUserRankNum(userYRankList, dbTombUser.getUserId());
            if (myRank <= this.getConfig().getMaxRank()) {
                userInfoBuilder.setRank(myRank);
            } else {
                userInfoBuilder.setRank(0);
            }
//            }
            builder.setUserInfo(userInfoBuilder);
            if (dbTombUser.getLockEvent().length() > 0) {
                DbTombPosition dbTombPosition = this.getDbData().getDbTombPosition(groupId, dbTombUser.getFloor(), dbTombUser.getLockEvent());
                if (dbTombPosition == null ||
                        dbTombPosition.getDone() == 1 ||
                        (dbTombPosition.geteType() != Tomb.EventEnum.EVENT_CHOOSE_VALUE && dbTombPosition.geteType() != Tomb.EventEnum.EVENT_TRAP_VALUE) ||
                        dbTombPosition.acquireDigUser() != dbTombUser.getUserId()) {
                    dbTombUser.setLockEvent("");
                    if (dbTombUser.getStatus() == 1) {
                        dbTombUser.setStatus(0);
                    }
                    dbTombUser.refreshUpdateTime();
                }
            }
            builder.setLockEvent(dbTombUser.getLockEvent());
            builder.setUseDoll(dbTombUser.getDollId());
            for (Map.Entry<Integer, Long> entry : dbTombUser.getDollMap().entrySet()) {
                Tomb.TombDollInfo.Builder dollBuilder = Tomb.TombDollInfo.newBuilder();
                dollBuilder.setDollId(entry.getKey());
                dollBuilder.setExpireTime(entry.getValue());
                builder.addDollInfo(dollBuilder);
            }
            builder.addAllSwitchCondition(dbTombUser.getSwitchList());
            builder.setGuideMark(dbTombUser.getGuideMark());
        }

    }


    public void userClick(long userId, Tomb.TombUserClickReq req, Tomb.TombUserClickResp.Builder builder) {
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId);
        if (dbTombUser == null) {
            builder.setRet(GameErrorCode.E_TOMB_USER_NOT_FOUND);
            return;
        }

        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        synchronized (dbTombUser.getPvpUnionChooseMap()) {
            if (dbTombUser.getStatus() != 2) {
                builder.setUserId(dbTombUser.getUserId());
                builder.setCurrentHp(dbTombUser.getHp());
                builder.setMaxHp(dbTombUser.getMaxHp());
                return;
            }

            int p = this.getConfig().getConfig().getTOMB_PVP_UNSTUN_CLICKS();

            double hp = Math.ceil((double) dbTombUser.getTotalHp() / (double) p);

            synchronized (dbTombUser.getPartnerUpgradeInfoMap()) {
                dbTombUser.setHp(dbTombUser.getHp() + (long) hp);
                dbTombUser.setMaxHp(dbTombUser.getTotalHp());
                if (dbTombUser.getHp() >= dbTombUser.getMaxHp()) {
                    dbTombUser.setHp(dbTombUser.getMaxHp());
                    dbTombUser.setStatus(0);

                    DbTombPosition dbTombPosition = this.dbData.getDbTombPosition(groupId, dbTombUser.getFloor(), dbTombUser.getLockEvent());
                    if (dbTombPosition != null && dbTombPosition.getDone() == 0 && dbTombPosition.geteType() == Tomb.EventEnum.EVENT_TRAP_VALUE) {
                        dbTombUser.setStatus(1);
                    }
                }
            }

            dbTombUser.refreshUpdateTime();

            builder.setUserId(dbTombUser.getUserId());
            builder.setCurrentHp(dbTombUser.getHp());
            builder.setMaxHp(dbTombUser.getMaxHp());

        }

    }


    public void eventExplore(long userId, Tomb.TombEventExploreReq req, Tomb.TombEventExploreResp.Builder builder) {
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId);
        if (dbTombUser == null) {
            return;
        }
        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        synchronized (dbTombUser.getPvpUnionChooseMap()) {
            TombMaze tombMaze = this.getTombMaze(groupId, dbTombUser.getFloor());
            tombMaze.eventExplore(dbTombUser, req, builder);
        }
    }

    public void eventInfo(long userId, Tomb.TombEventInfoReq req, Tomb.TombEventInfoResp.Builder builder) {
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId);
        if (dbTombUser == null) {
            return;
        }
        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        synchronized (dbTombUser.getPvpUnionChooseMap()) {
            TombMaze tombMaze = this.getTombMaze(groupId, dbTombUser.getFloor());
            tombMaze.eventInfo(dbTombUser, req, builder);
        }
    }

    public void eventTouch(long userId, Tomb.TombEventTouchReq req, Tomb.TombEventTouchResp.Builder builder) {
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId);
        if (dbTombUser == null) {
            return;
        }
        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        synchronized (dbTombUser.getPvpUnionChooseMap()) {
            if (dbTombUser.getStatus() == 2) {
                builder.setRet(GameErrorCode.E_TOMB_USER_IS_NOT_ALIVE);
                return;
            }
            TombMaze tombMaze = this.getTombMaze(groupId, dbTombUser.getFloor());
            tombMaze.eventTouch(dbTombUser, req, builder);
        }

    }

    public void heartbeat(long userId, Tomb.TombHeartbeatReq req, Tomb.TombHeartBeatResp.Builder builder) {
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId);
        this.heartbeat.handle(dbTombUser, req);
    }

    public void partnerInfo(long userId, Tomb.TombPartnerInfoResp.Builder builder) {
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId);
        if (dbTombUser == null) {
            return;
        }
        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        TombMaze tombMaze = this.getTombMaze(groupId, dbTombUser.getFloor());
        if (tombMaze == null) {
            return;
        }
        builder.setTotalAttack(dbTombUser.getTotalAttackWithoutAddition());
        builder.setTotalHp(dbTombUser.getTotalHpWithoutAddition());
        builder.setAttackAddition(dbTombUser.getAttackAddition());
        builder.setHpAddition(dbTombUser.getHpAddition());

    }

    public void mazeInfo(long userId, Tomb.TombMazeInfoResp.Builder builder) {
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId);
        if (dbTombUser == null) {
            return;
        }
        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        TombMaze tombMaze = this.getTombMaze(groupId, dbTombUser.getFloor());
        if (tombMaze == null) {
            return;
        }
        builder.setExploredNum(0);
        ActivityTombFloor activityTombFloor = this.getConfig().getFloor(tombMaze.getFloor());
        builder.setTotalExploreNum(activityTombFloor.getTotalEventNum());
        dbTombUser.setGuideMark(1);
        builder.setGuideMark(1);
        for (Position position : tombMaze.getBuffEventMap().values()) {
            Tomb.TombBuffEventTemp.Builder temp = Tomb.TombBuffEventTemp.newBuilder();
            Tomb.CoordinateTemp.Builder coordinate = Tomb.CoordinateTemp.newBuilder();
            coordinate.setRow(position.getRow());
            coordinate.setColumn(position.getColumn());
            coordinate.setFloor(tombMaze.getFloor());
            temp.setCoordinate(coordinate);
            DbTombUserPosition dbTombUserPosition = this.dbData.getDbTombUserPosition(dbTombUser.getGroupId(), tombMaze.getFloor(), userId, position.getRow(), position.getColumn());
            if (dbTombUserPosition != null) {
                if (dbTombUserPosition.getRelationId() > 0) {
                    temp.setIsOver(true);
                    builder.addBuffEventList(temp);
                    continue;
                }

            }
            temp.setIsOver(false);
            builder.addBuffEventList(temp);
        }

    }

    public void fastestPlayer(long userId, Tomb.TombFastestPlayerResp.Builder builder) {
        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        TombMaze tombMaze = this.getTombMaze(groupId, this.dbData.getDbActivityTombInfo(groupId).getMaxExploreFloor());
        List<DbTombUser> dbTombUserRanking = this.getDbData().getDbTombUserRanking(groupId);
        dbTombUserRanking.sort(Comparator.comparing(DbTombUser::getScore).reversed());
        DbTombUser dbTombUser = null;
        for (DbTombUser _dbTombUser : dbTombUserRanking) {
            if (_dbTombUser.getFloor() != this.getDbData().getDbActivityTombInfo(groupId).getMaxExploreFloor()) {
                continue;
            }
            dbTombUser = _dbTombUser;
            break;
        }
        if (dbTombUser != null) {
            builder.setPlayerBaseData(dbTombUser.toPlayerBaseTempBuilder());
            builder.setUserId(dbTombUser.getUserId());
        }
        builder.setFloor(tombMaze.getFloor());
        builder.setBossFloor(this.dbData.getDbActivityTombInfo(groupId).getBossFloor());
        builder.setIsBossFound(false);

        Map<Integer, TombMaze> mazeMap = this.getTombMazeMap().get(groupId); // 活动陵墓地图集合
        int maxExploreFloor = this.dbData.getDbActivityTombInfo(groupId).getMaxExploreFloor();
        // 特殊处理情况，假设当前11层boss已被击杀发现入口，但是未有玩家进入12层，此时一键跳转到12层
        if (mazeMap.containsKey(maxExploreFloor)) {
            TombMaze maze = mazeMap.get(maxExploreFloor);
            String posKey = maze.getDbTombMaze().getEliteNpcEvent(); // 当前层守关精英位置
            // 获取当前层守关精英事件信息，判断是否有玩家处理了该事件
            DbTombPosition dbTombPosition = this.getDbData().getDbTombPosition(groupId, maxExploreFloor, posKey);
            if (dbTombPosition != null && dbTombPosition.getFinishUserId() > 0) {
                maxExploreFloor++;
            }
        }
        builder.setMaxExploreFloor(maxExploreFloor);
    }

    public synchronized void unionInTrapHelp(long userId, Tomb.TombUnionInTrapHelpReq req, Tomb.TombUnionInTrapHelpResp.Builder builder) {

        DbTombUser dbTombUser = this.dbData.getDbTombUser(req.getUserId());
        if (dbTombUser == null) {
            builder.setRet(GameErrorCode.E_TOMB_USER_NOT_FOUND);
            return;
        }
        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        builder.setOverTimestamp(0);
        builder.setRemain(0);
        DbTombPosition dbTombPosition = this.getDbData().getDbTombPosition(groupId, dbTombUser.getFloor(), dbTombUser.getPositionKey());
        if (dbTombPosition == null) {
            return;
        }
        if (dbTombUser.getStatus() != 1) {
            builder.setRemain(0);
            return;
        }

        ActivityTombEvent activityTombEvent = this.config.getEvent(dbTombPosition.getEventId());
        int p3 = activityTombEvent.getParam1().get(2);
        builder.setOverTimestamp(dbTombPosition.getOverTime());
        if (req.getIsCheck() || dbTombPosition.getHelpUserIdList().contains(userId)) {
            builder.setRemain(dbTombPosition.getHelpUserIdList().size() - p3);
            builder.addAllUserId(dbTombPosition.getHelpUserIdList());
            return;
        }
        if (dbTombPosition.getHelpUserIdList().size() >= p3) {
            builder.addAllUserId(dbTombPosition.getHelpUserIdList());
            return;
        }
        DbTombUser helpDbTombUser = this.dbData.getDbTombUser(userId);
        helpDbTombUser.setUserInfo(UserInfo.newInstance(req.getPlayerBase()));
        helpDbTombUser.refreshUpdateTime();

        dbTombPosition.getHelpUserIdList().add(userId);
        builder.setRemain(p3 - dbTombPosition.getHelpUserIdList().size());
        builder.addAllUserId(dbTombPosition.getHelpUserIdList());


        Tomb.TombUnionInTrapSavePush.Builder pushBuilder = Tomb.TombUnionInTrapSavePush.newBuilder();
        pushBuilder.setSaveUserId(req.getUserId());
        for (long aLong : dbTombPosition.getHelpUserIdList()) {
            DbTombUser dbTombUser1 = this.dbData.getDbTombUser(aLong);
            pushBuilder.addList(dbTombUser1.toPlayerBaseTempBuilder());
        }

        dbTombPosition.refreshUpdateTime();
        MessageHelper.sendToGameServer(dbTombUser.getUserInfo().getServerId(), GameProtocol.S_TOMB_UNION_IN_TRAP_SAVE_PUSH, this.activityInfo.getActivityId(), req.getUserId(), pushBuilder, null);

        if (dbTombPosition.getHelpUserIdList().size() == p3) {
            Tomb.AllyInfo.Builder allyInfoBuilder = dbTombUser.toAllyInfoBuilder();
            allyInfoBuilder.addAllHelpUserId(dbTombPosition.getHelpUserIdList());
            allyInfoBuilder.setIsInTrap(false);
            this.moveNotify(dbTombUser.getFloor(), null, dbTombUser, null, allyInfoBuilder);
        }


    }

    public synchronized void unionInTrapSendHelp(long userId, Tomb.TombUnionInTrapSendHelpReq req, Tomb.TombUnionInTrapSendHelpResp.Builder builder) {
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId);
        if (dbTombUser == null) {
            builder.setRet(GameErrorCode.E_TOMB_USER_NOT_FOUND);
            return;
        }

        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        DbTombPosition dbTombPosition = this.dbData.getDbTombPosition(groupId, dbTombUser.getFloor(), dbTombUser.getLockEvent());
        if (dbTombPosition == null || dbTombPosition.getDone() == 1 || dbTombPosition.geteType() != Tomb.EventEnum.EVENT_TRAP_VALUE) {
            return;
        }
        dbTombPosition.setIsSendHelp(1);
        builder.setOverTimestamp(dbTombPosition.getOverTime());
        builder.setRow(dbTombPosition.getX());
        builder.setColumn(dbTombPosition.getY());
        builder.setFloor(dbTombUser.getFloor());
        dbTombPosition.refreshUpdateTime();

        Tomb.AllyInfo.Builder allyInfoBuilder = dbTombUser.toAllyInfoBuilder();
        allyInfoBuilder.addAllHelpUserId(dbTombPosition.getHelpUserIdList());
        allyInfoBuilder.setIsSendHelp(true);
        allyInfoBuilder.setOverTimestamp(dbTombPosition.getOverTime());
        this.moveNotify(dbTombUser.getFloor(), null, dbTombUser, null, allyInfoBuilder);

    }

    public void buffRefreshPartner(DbTombUser dbTombUser, Tomb.TombBuffRefreshPartnerReq req, Tomb.TombBuffRefreshPartnerResp.Builder builder, CompletableFuture<AbstractMessage.Builder<?>> completableFuture) {
        TombMaze tombMaze = this.getTombMaze(dbTombUser.getGroupId(), dbTombUser.getFloor());
        if (tombMaze == null) {
            builder.setRet(GameErrorCode.E_ERROR_DATA);
            completableFuture.complete(builder);
            return;
        }

        Position position = tombMaze.getRealPosition(req.getCoordinate().getRow(), req.getCoordinate().getColumn());
        if (position == null) {
            builder.setRet(GameErrorCode.E_ERROR_DATA);
            completableFuture.complete(builder);
            return;
        }
        if (position.geteType() != Tomb.EventEnum.EVENT_BUFF_VALUE) {
            builder.setRet(GameErrorCode.E_ERROR_DATA);
            completableFuture.complete(builder);
            return;
        }

        DbTombUserPosition dbTombUserPosition = this.dbData.getDbTombUserPosition(dbTombUser.getGroupId(), req.getCoordinate().getFloor(), dbTombUser.getUserId(), req.getCoordinate().getRow(), req.getCoordinate().getColumn());
        if (dbTombUserPosition == null) {
            builder.setRet(GameErrorCode.E_ERROR_DATA);
            completableFuture.complete(builder);
            return;
        }

        if (dbTombUserPosition.getRelationIdList().size() == 0) {
            builder.setRet(GameErrorCode.E_ERROR_DATA);
            completableFuture.complete(builder);
            return;
        }

        Tomb.TombUserCostItemReq.Builder costItemReq = Tomb.TombUserCostItemReq.newBuilder();

        Property property = new Property(this.config.getConfig().getTOMB_ADD_EVENT_REFRESH_COST());

        costItemReq.setRewards(PropertyHelper.parsePropertyToString(property));
        //通知游戏服扣除
        Tomb.TombUserCostItemResp.Builder userAddItemRespBuilder = Tomb.TombUserCostItemResp.newBuilder();
        CompletableFuture<SyncResponse> syncResponseFuture = MessageHelper.sendToGameServer(dbTombUser.getUserInfo().getServerId(), GameProtocol.S_TOMB_USER_COST_ITEM_CROSS_TO_GAME, tombMaze.getActivityId(), dbTombUser.getUserId(), costItemReq, userAddItemRespBuilder);
        syncResponseFuture.thenAccept(syncResponse -> {
            if (syncResponse.getErrorCode() != 0) {
                builder.setRet(syncResponse.getErrorCode());
                completableFuture.complete(builder);
                return;
            }
            Set<Integer> randPartnerList = tombMaze.randPartnerList(dbTombUser);
            dbTombUserPosition.setRelationIdList(randPartnerList);

            ActivityTombEvent activityTombEvent = this.config.getEvents(1).get(0);

            int p1 = activityTombEvent.getParam1().get(0);
            int p2 = activityTombEvent.getParam1().get(1);
            for (Integer integer : dbTombUserPosition.getRelationIdList()) {
                Tomb.PartnerTemp.Builder p = Tomb.PartnerTemp.newBuilder();
                PartnerInfo partnerInfo = dbTombUser.acquirePartnerInfo(integer);
                PartnerUpgradeInfo partnerUpgradeInfo = dbTombUser.acquirePartnerUpgradeInfo(integer);
                p.setId(integer);
                p.setBaseEarn(partnerInfo.getAbility());
                p.setEarn(partnerUpgradeInfo.getResultAbility(partnerInfo.getAbility()));
                p.setUpgradeTimes(partnerUpgradeInfo.getTimes());
                p.setUpgradeValue(partnerUpgradeInfo.getResultUpgradeAbility(partnerInfo.getAbility(), p1, p2) - partnerUpgradeInfo.getResultAbility(partnerInfo.getAbility()));
                p.setPercentage(partnerUpgradeInfo.getPercentage());
                p.setFixedValue(partnerUpgradeInfo.getFixedValue());
                builder.addList(p);
            }
            completableFuture.complete(builder);
        });
    }

    public void eventTakeCare(long userId, Tomb.TombEventTakeCareReq req, Tomb.TombEventExploreResp.Builder builder) {
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId);
        if (dbTombUser == null) {
            builder.setRet(GameErrorCode.E_TOMB_USER_NOT_FOUND);
            return;
        }
        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        synchronized (dbTombUser.getPvpUnionChooseMap()) {
            TombMaze tombMaze = this.getTombMaze(groupId, dbTombUser.getFloor());
            if (tombMaze == null) {
                builder.setRet(GameErrorCode.E_ERROR_DATA);
                return;
            }
            if (!TombServiceMgr.canTakeCare(activityInfo.getActivityId(), dbTombUser)) {
                builder.setRet(GameErrorCode.E_TOMB_NO_UNLOCK_PAY_DOLL);    //没解锁付费人偶
                return;
            }
            tombMaze.eventTakeCare(dbTombUser, req, builder);
        }
    }


    public DbTombMaze initDbTombMaze(int groupId, int floor) {
        int eventNum = this.config.getConfig().getTOMB_EVENT_NUM_PARAM().get(2);
        if (this.dbData.getDbActivityTombInfo(groupId).getGenerateEventNum() > eventNum) {
            eventNum = this.dbData.getDbActivityTombInfo(groupId).getGenerateEventNum();
        }

        List<EventInfo> eventInfoList = this.config.generateEventWeight(floor, eventNum);
        ActivityTombFloor activityTombFloor = this.config.getFloor(floor);

        int totalBigBox = this.config.getTotalBigGrip(eventInfoList);
        int buffEventNum = activityTombFloor.getBuffEventNum();
        int totalBigEventNum = this.config.getTotalBigEventNum(eventInfoList);
        int totalNormalEventNum = this.config.getTotalNormalEventNum(eventInfoList);
        DbTombMaze dbTombMaze = DbTombMaze.newInstance();
        dbTombMaze.setGenerateEventNum(eventNum);
        dbTombMaze.setGroupId(groupId);
        dbTombMaze.setNeedInsert(true);
        logger.info("开始生成的地图，组{} 第{}层", groupId, floor);
        for (int i = 0; i < 100; i++) {
            Maze maze = Maze.newMaze(this.config.getDoorNum(), totalBigBox, buffEventNum, totalBigEventNum, totalNormalEventNum);
            if (maze.generate()) {
                dbTombMaze.setMaze(maze);
                logger.info("生成的地图合格第{}次", i);
                break;
            }
            logger.info("生成的地图不合格，重新生成，第{}次", i);
        }

        dbTombMaze.setActivityId(this.activityInfo.getActivityId());
        dbTombMaze.setFloor(floor);

        dbTombMaze.setEventInfoList(eventInfoList);

        int i = activityTombFloor.randEliteNpc();
        dbTombMaze.setEliteEventId(i);
        dbTombMaze.refreshUpdateTime();

        return dbTombMaze;
    }

    public TombMaze getTombMaze(int groupId, int floor) {
        if(!tombMazeMap.containsKey(groupId)){
            return null;
        }
        TombMaze tombMaze = this.tombMazeMap.get(groupId).get(floor);
        if (tombMaze != null) {
            return tombMaze;
        }
        return null;
    }


    public List<DbTombUser> getSortDbTombUserList(int groupId) {
        ArrayList<DbTombUser> dbTombUsers = new ArrayList<>();
        for (DbTombUser value : this.dbData.getDbTombUserMap().values()) {
            if(value.getGroupId() == groupId){
                dbTombUsers.add(value);
            }
        }
        dbTombUsers.sort(Comparator.comparing(DbTombUser::getRewardScore).reversed());
        return dbTombUsers;
    }

    public ActivityInfo getActivityInfo() {
        return activityInfo;
    }

    public Map<Integer, Map<Integer, TombMaze>> getTombMazeMap() {
        return tombMazeMap;
    }

    public Map<Integer, TombMaze> getTombMazeMap(int groupId) {
        return tombMazeMap.get(groupId);
    }


    public TombHeartbeat getHeartbeat() {
        return heartbeat;
    }

    public TombActivityUnion getActivityUnion(String unionUid) {
        if (!this.activityUnionMap.containsKey(unionUid)) {
            TombActivityUnion tombActivityUnion = TombActivityUnion.newInstance(this, unionUid);
            this.activityUnionMap.put(unionUid, tombActivityUnion);
        }
        return this.activityUnionMap.get(unionUid);
    }

    public Map<String, TombActivityUnion> getActivityUnionMap() {
        return activityUnionMap;
    }

    public TombConfig getConfig() {
        return config;
    }


    public TombLog getTombLog() {
        return tombLog;
    }

    public TombDbData getDbData() {
        return dbData;
    }


    public ActivityTombRepair[] getTombRepairConfig() {
        return this.config.getRepairs();
    }


    public void updateDbUser(long userId, long serverId, Tomb.TombActivityInfoToCrossReq req, Tomb.TombActivityInfoResp.Builder builder) {
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId);
        if (dbTombUser == null) {
            return;
        }
        synchronized (dbTombUser.getPvpUnionChooseMap()) {
            UserInfo userInfo = UserInfo.newInstance(req.getPlayerBaseData());
            dbTombUser.setUserInfo(userInfo);
            dbTombUser.setAttackAddition(req.getAttackAddition());
            dbTombUser.setHpAddition(req.getHpAddition());

            builder.setPersonalScore(dbTombUser.getScore());
            builder.setUnionScore(dbTombUser.getUnionScore());

            //初始化黏土使用排名
            this.getActivityUnion(dbTombUser.getUserInfo().getUnionUid()).updateNiantuRank(dbTombUser);
        }

    }

    public boolean isFinalBoss(int groupId, int floor) {
        if (floor == this.dbData.getDbActivityTombInfo(groupId).getBossFloor()) {
            return true;
        }
        return false;
    }

    public int updateUserSwitch(long userId, List<Integer> switchList) {
        DbTombUser dbTombUser = this.getDbData().getDbTombUser(userId);
        if (dbTombUser == null) {
            return GameErrorCode.E_TOMB_USER_NOT_FOUND;
        }
        synchronized (dbTombUser.getPvpUnionChooseMap()) {
            Map<Integer, Long> dollMap = dbTombUser.getDollMap();
            int takeCareDollId = config.getConfig().getTOMB_ALL_DOLL_ID_LIST().get(1);
            if (dollMap.get(takeCareDollId) >= System.currentTimeMillis()) {
                dbTombUser.setSwitchList(switchList);
                dbTombUser.refreshUpdateTime();
            } else {
                return GameErrorCode.E_TOMB_NO_UNLOCK_PAY_DOLL;
            }
            return 0;
        }
    }

    public long getTotalActiveUserAbility(int groupId) {
        UnionActivityGroup group = Cross2UnionActivityGroupMgr.getGroupData(activityInfo.getActivityId(), groupId);
        long total = 0;
        for (TombActivityUnion tombActivityUnion : this.getActivityUnionMap().values()) {
            if (StringUtils.isNullOrEmpty(tombActivityUnion.getUnionUid())) {
                continue;
            }
            if(group != null && group.getUnionDataMap().keySet().size() != 0 && group.getUnionDataMap().get(tombActivityUnion.getUnionUid()) == null){
                continue;
            }
            long totalActiveUserAbility = tombActivityUnion.getTotalActiveUserAbility();
            total = total + totalActiveUserAbility;
        }
        if (total <= 0) {//防止血量有0的情况,重新加一次,并且不判断空商会
            for (TombActivityUnion tombActivityUnion : this.getActivityUnionMap().values()) {
                long totalActiveUserAbility = tombActivityUnion.getTotalActiveUserAbility();
                total = total + totalActiveUserAbility;
            }
            logger.error("皇陵活动{},总血量为0,重新计算后={}", this.activityInfo.getActivityId(), total);
        }
        return total;
    }

    public void moveNotify(int floor, Tomb.CoordinateTemp from, DbTombUser dbTombUser, List<Tomb.CoordinateTemp> path, Tomb.AllyInfo.Builder allyInfoBuilder) {
        Tomb.TombMazeAllyMoveNotifyResp.Builder builder = Tomb.TombMazeAllyMoveNotifyResp.newBuilder();
        if (from != null) {
            builder.setFrom(from);
        }
        builder.setAllyInfo(allyInfoBuilder);
        if (path != null) {
            builder.addAllPath(path);
        }
        List<HeartbeatInfo> heartbeatInfoList = this.getHeartbeat().getList(dbTombUser.getGroupId());
        Map<Long, Tomb.TombMazeAllyMoveNotifyCrossToGameReq.Builder> toGameReqMap = new HashMap<>();
        for (HeartbeatInfo value : heartbeatInfoList) {
            if (value.getFloor() != floor) {
                continue;
            }
            if (dbTombUser.getUserId() == value.getUserId()) {
                continue;
            }
            if (!toGameReqMap.containsKey(value.getServerId())) {
                toGameReqMap.put(value.getServerId(), Tomb.TombMazeAllyMoveNotifyCrossToGameReq.newBuilder().setResp(builder));
            }
            toGameReqMap.get(value.getServerId()).addUserIdList(value.getUserId());
        }
        toGameReqMap.forEach((serverId, req) -> {
            MessageHelper.sendToGameServer(serverId, GameProtocol.S_TOMB_MAZE_ALLY_MOVE_NOTIFY_CROSS_TO_GAME, this.activityInfo.getActivityId(), 0, req, null);
        });
    }


    public List<Tomb.AllyInfo> getAlliInfoList(int floor, long userId, String unionUid) {
        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId);
        List<Tomb.AllyInfo> list = new ArrayList<>();
        List<HeartbeatInfo> heartbeatInfoList = this.getHeartbeat().getList(groupId);
        for (HeartbeatInfo heartbeatInfo : heartbeatInfoList) {
            if (heartbeatInfo.getUserId() == userId) {
                continue;
            }
            if (heartbeatInfo.getFloor() != floor) {
                continue;
            }
            DbTombUser dbTombUser = this.getDbData().getDbTombUser(heartbeatInfo.getUserId());
            if (dbTombUser == null) {
                continue;
            }
            Tomb.AllyInfo.Builder allyInfoBuilder = dbTombUser.toAllyInfoBuilder();
            if (dbTombUser.getLockEvent().length() > 0) {
                DbTombPosition dbTombPosition = this.dbData.getDbTombPosition(groupId, dbTombUser.getFloor(), dbTombUser.getLockEvent());
                if (dbTombPosition != null && dbTombPosition.getDone() == 0 && dbTombPosition.geteType() == Tomb.EventEnum.EVENT_TRAP_VALUE) {
                    continue;
                }
            }
            allyInfoBuilder.setIsInTrap(false);
            list.add(allyInfoBuilder.build());
        }

        Map<String, DbTombPosition> dbTombPositionMap = this.getDbData().getDbTombPositionMap(groupId, floor);
        if (dbTombPositionMap != null) {
            for (DbTombPosition dbTombPosition : dbTombPositionMap.values()) {
                if (dbTombPosition != null && dbTombPosition.getDone() == 0 && dbTombPosition.geteType() == Tomb.EventEnum.EVENT_TRAP_VALUE) {
                    long userId1 = dbTombPosition.acquireDigUser();
                    if (userId1 == userId) {
                        continue;
                    }
                    DbTombUser dbTombUser = this.getDbData().getDbTombUser(userId1);
                    if (dbTombUser == null) {
                        continue;
                    }
                    if (System.currentTimeMillis() > dbTombPosition.getOverTime()) {
                        continue;
                    }
                    ActivityTombEvent activityTombEvent = this.config.getEvent(dbTombPosition.getEventId());
                    int p3 = activityTombEvent.getParam1().get(2);
                    if (dbTombPosition.getHelpUserIdList().size() >= p3) {
                        continue;
                    }
                    Tomb.AllyInfo.Builder allyInfoBuilder = dbTombUser.toAllyInfoBuilder();
                    allyInfoBuilder.setIsSendHelp(dbTombPosition.getIsSendHelp() == 1);
                    allyInfoBuilder.setOverTimestamp(dbTombPosition.getOverTime());
                    allyInfoBuilder.addAllHelpUserId(dbTombPosition.getHelpUserIdList());
                    allyInfoBuilder.setIsInTrap(true);
                    list.add(allyInfoBuilder.build());
                }
            }
        }
        return list;
    }


    /**
     * 获取人偶积分加成  千分比
     */

    public int getDollScoreBuffPercentage(DbTombUser dbTombUser) {
        int scoreDollId = this.getConfig().getConfig().getTOMB_ALL_DOLL_ID_LIST().get(2);       //默认|打理|积分
        Map<Integer, Long> dollMap = dbTombUser.getDollMap();
        if (dollMap.get(scoreDollId) >= System.currentTimeMillis()) {
            GoodsInfo goodsInfo = GoodsMgr.getGoodsInfo(scoreDollId);
            return goodsInfo.getParamList().get(1).intValue();      //看加成
        }
        return 0;
    }


    public void sendLogToGame(DbTombUser dbTombUser, Tomb.TombLogCrossToGameReq.Builder builder) {
        MessageHelper.sendToGameServer(dbTombUser.getUserInfo().getServerId(), GameProtocol.S_TOMB_LOG_CROSS_TO_GAME, this.getActivityInfo().getActivityId(), dbTombUser.getUserId(), builder, null);
    }

    public boolean getInitialized(int groupId) {
        if(!initializedMap.containsKey(groupId)){
            return false;
        }
        return initializedMap.get(groupId).get();
    }

    public void setInitialized(int groupId, boolean b) {
        if(!initializedMap.containsKey(groupId)){
            initializedMap.put(groupId, new AtomicBoolean(false));
        }
        this.initializedMap.get(groupId).set(b);
    }


    public void checkOffline() {
        List<HeartbeatInfo> heartbeatInfoList = this.getHeartbeat().getOfflineList();
        for (HeartbeatInfo heartbeatInfo : heartbeatInfoList) {
            DbTombUser dbTombUser = this.getDbData().getDbTombUser(heartbeatInfo.getUserId());
            Tomb.AllyInfo.Builder builder = dbTombUser.toAllyInfoBuilder();
            builder.setOffline(true);
            this.moveNotify(heartbeatInfo.getFloor(), null, dbTombUser, null, builder);
        }
    }

    public void clearDbTombPosition(int groupId) {
        long now = System.currentTimeMillis();

        for (Map.Entry<Integer, Map<Integer, Map<String, DbTombPosition>>> entry : this.getDbData().getDbTombPositionMap().entrySet()) {
            if(entry.getKey() != groupId){
                continue;
            }
            for (Map.Entry<Integer, Map<String, DbTombPosition>> mapEntry : entry.getValue().entrySet()) {
                Map<String, DbTombPosition> dbTombPositionMap = mapEntry.getValue();
                for (DbTombPosition dbTombPosition : dbTombPositionMap.values()) {
                    if (dbTombPosition.getDone() != 1) {
                        continue;
                    }
                    if (now - dbTombPosition.getUpdateTime() < 1000 * 60 * 10) {
                        continue;
                    }
                    dbTombPositionMap.remove(dbTombPosition.getKey());
                }
            }
        }

        for (TombActivityUnion tombActivityUnion : this.getActivityUnionMap().values()) {
            for (Map<String, DbTombPosition> dbTombPositionMap : tombActivityUnion.getDbTombPositionMapMap().values()) {
                for (DbTombPosition dbTombPosition : dbTombPositionMap.values()) {
                    if (dbTombPosition.getDone() != 1) {
                        continue;
                    }
                    if (now - dbTombPosition.getUpdateTime() < 1000 * 60 * 10) {
                        continue;
                    }
                    dbTombPositionMap.remove(dbTombPosition.getKey());
                }
            }
        }
    }

    public void clearPositionMapData() {
        for (Map.Entry<Integer, Map<Integer, TombMaze>> entry : this.getTombMazeMap().entrySet()) {
            for (Map.Entry<Integer, TombMaze> mazeEntry : entry.getValue().entrySet()) {
                TombMaze tombMaze = mazeEntry.getValue();
                if (tombMaze.getDbTombMaze().getFirstIntoUserId() == 0) {
                    continue;
                }
                long start = System.currentTimeMillis();
                int i = tombMaze.clearPositionMapData();
                long end = System.currentTimeMillis();
                logger.info("clearPositionMap activityId:{}, groupId:{}, floor:{}, num:{}, costTime:{}",  entry.getKey(), this.getActivityInfo().getActivityId(), tombMaze.getFloor(), i, end - start);
            }
        }
    }

    public synchronized void trapInfoList(int groupId, Tomb.TombTrapInfoReqMsg req, Tomb.TombTrapInfoRespMsg.Builder builder) {
        for (Tomb.TombTrapInfoTemp tombTrapInfoTemp : req.getListList()) {
            Tomb.TombTrapInfoTemp.Builder tombTrapInfoTempBuilder = tombTrapInfoTemp.toBuilder();
            tombTrapInfoTempBuilder.setOverTimestamp(0);

            DbTombPosition dbTombPosition = this.getDbData().getDbTombPosition(groupId, tombTrapInfoTempBuilder.getFloor(), String.format("%d_%d", tombTrapInfoTempBuilder.getRow(), tombTrapInfoTempBuilder.getColumn()));
            if (dbTombPosition == null ||
                    dbTombPosition.getDone() == 1 ||
                    dbTombPosition.geteType() != Tomb.EventEnum.EVENT_TRAP_VALUE ||
                    dbTombPosition.acquireDigUser() != tombTrapInfoTempBuilder.getUserId()) {
                builder.addList(tombTrapInfoTempBuilder);
                continue;
            }

            tombTrapInfoTempBuilder.setOverTimestamp(dbTombPosition.getOverTime());
            tombTrapInfoTempBuilder.addAllHelpUserId(dbTombPosition.getHelpUserIdList());
            builder.addList(tombTrapInfoTempBuilder);
        }
    }

    /**
     * 秦始皇陵一键跳转至活动已解锁的最深层
     *
     * @param userId  玩家ID
     * @param builder 返回构建
     */
    public void eventOneClickJump(long userId, Tomb.TombOneClickJumpResp.Builder builder) {
        DbTombUser dbTombUser = this.dbData.getDbTombUser(userId); // 玩家在活动中的信息
        if (dbTombUser == null) {
            return;
        }

        int groupId = Cross2UnionActivityGroupMgr.getGroupId(activityInfo.getActivityId(), userId); // 跨服商会分组ID
        synchronized (dbTombUser.getPvpUnionChooseMap()) {
            TombMaze tombMaze = this.getTombMaze(groupId, dbTombUser.getFloor()); // 获取玩家所在层的地图信息
            if (tombMaze == null) {
                builder.setRet(GameErrorCode.E_TOMB_MAZE_FLOOR_NOT_FOUND);
                return;
            }
            Buff buff = new Buff();
            buff.oneClickBuff(groupId, dbTombUser, builder, this, tombMaze); // 一键获取途经所有天玄枢机增益，包括当前层未获取完毕的
        }
    }
}


